package cn.iocoder.yudao.module.erp.service.priwarehouseintegra;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
import cn.iocoder.yudao.module.bpm.service.task.BpmTasktooService;
import cn.iocoder.yudao.module.erp.controller.admin.priwarehouseintegra.vo.PriWarehouseIntegraPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.priwarehouseintegra.vo.PriWarehouseIntegraSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.deppurchaseitem.DepPurchaseItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.priwarehouseintegra.PriWarehouseIntegraDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purpurchaseorder.PurPurchaseOrderDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purpurchaseorderitem.PurPurchaseOrderItemDO;
import cn.iocoder.yudao.module.erp.dal.mysql.deppurchaseitem.DepPurchaseItemMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.priwarehouseintegra.PriWarehouseIntegraMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.purpurchaseorder.PurPurchaseOrderMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.purpurchaseorderitem.PurPurchaseOrderItemMapper;
import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
import com.alibaba.excel.util.StringUtils;
import jakarta.annotation.Resource;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * ERP 一级库整合单 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class PriWarehouseIntegraServiceImpl implements PriWarehouseIntegraService {

    @Resource
    private PriWarehouseIntegraMapper priWarehouseIntegraMapper;
    @Resource
    private PurPurchaseOrderMapper purPurchaseOrderMapper;
    @Resource
    private PurPurchaseOrderItemMapper purPurchaseOrderItemMapper;
    @Resource
    private DepPurchaseItemMapper depPurchaseItemMapper;
    @Resource
    private ErpNoRedisDAO noRedisDAO;
    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private BpmTasktooService bpmTasktooService;

    @Value("${erp.purchaseOrder.processKey}")
    private String processKey;

    @Value("${erp.purchaseOrder.taskname1}")
    private String taskname1;

    @Value("${erp.purchaseOrder.taskname2}")
    private String taskname2;

    @Value("${erp.purchaseOrder.taskname3}")
    private String taskname3;

    @Override
    public Long createPriWarehouseIntegra(Long userId, PriWarehouseIntegraSaveReqVO createReqVO) {
        // 插入
        PriWarehouseIntegraDO priWarehouseIntegra = BeanUtils.toBean(createReqVO, PriWarehouseIntegraDO.class);
        priWarehouseIntegraMapper.insert(priWarehouseIntegra);
        if (!StringUtils.isEmpty(processKey)) {
            // 发起 BPM 流程  加这里
            Map<String, Object> processInstanceVariables = new HashMap<>();
            // processInstanceVariables.put("day", processKey);
            String processInstanceId = processInstanceApi.createProcessInstance(userId,
                    new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(processKey)
                            .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(priWarehouseIntegra.getId()))
                            .setStartUserSelectAssignees(createReqVO.getStartUserSelectAssignees()));

            // 将工作流的编号，更新到 OA 请假单中
            priWarehouseIntegraMapper.updateById(new PriWarehouseIntegraDO().setId(priWarehouseIntegra.getId()).setProcessInstanceId(processInstanceId));
        }
        // 返回
        return priWarehouseIntegra.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createPurPurchaseOrder(PriWarehouseIntegraSaveReqVO createReqVO) {
        // 根据整合单查询所有订单
        List<DepPurchaseItemDO> DepPurchaseItemDOs = depPurchaseItemMapper.getDepPurchaseItemByPriWarehouseIntegraId(createReqVO.getIntegrateId());
        if (DepPurchaseItemDOs == null || DepPurchaseItemDOs.size() == 0) {
            throw exception(ERP_DEP_PURCHASE_ITEM_NOT_EXISTS);
        }
        // 循环整合单项找打共同供应商的项
        // 先找到供应商
//        HashSet<Long> deptIds = new HashSet<>();
//        for (DepPurchaseItemDO depPurchaseItem : DepPurchaseItemDOs) {
//            // 根据部门id区分
//            deptIds.add(depPurchaseItem.getDeptId());
//        }
        List<DepPurchaseItemDO> supplierDeptIds = DepPurchaseItemDOs.stream()
                .collect(Collectors.toMap(
                        DepPurchaseItemDO::getSupplierDeptId, // 以name属性作为键
                        DepPurchaseItemDO -> DepPurchaseItemDO, // 值是Person对象本身
                        (existing, replacement) -> existing // 如果有重复的键，保留第一个
                ))
                .values()
                .stream()
                .collect(Collectors.toList());
        if (supplierDeptIds == null || supplierDeptIds.size() == 0) {
            return null;
        }
        List<PurPurchaseOrderDO> purPurchaseOrderDOS = new ArrayList<>();
        List<PurPurchaseOrderItemDO> purPurchaseOrderItemDOList = new ArrayList<>();
        // 循环供应商，分别找到供应商的订单项
        for (DepPurchaseItemDO depPurchaseItemDO : supplierDeptIds) {
            // 采购单
            PurPurchaseOrderDO purPurchaseOrderDO = new PurPurchaseOrderDO();

            String id = UUID.randomUUID().toString();
            // 主键
            purPurchaseOrderDO.setId(id);
            // 供应商
            purPurchaseOrderDO.setSupplierId(depPurchaseItemDO.getSupplierId());
            // 供应商部门
            purPurchaseOrderDO.setDeptId(depPurchaseItemDO.getSupplierDeptId());
            // 一级库整合单编号
            purPurchaseOrderDO.setIntegrateId(createReqVO.getIntegrateId());
            // 流程实例的编号
            purPurchaseOrderDO.setProcessInstanceId(createReqVO.getProcessInstanceId());
            //  采购单编号，并校验唯一性
            String no = noRedisDAO.generate(ErpNoRedisDAO.PURPURCHASEOEDER_ORDER_NO_PREFIX);
            if (purPurchaseOrderMapper.selectByNo(no) != null) {
                throw exception(PUR_PURCHASE_CHECK_NO_EXISTS);
            }
            // String purChaseOrderId = UUID.randomUUID().toString();
            purPurchaseOrderDO.setPurchaseOrderId(no);
            // 主单编号
//            purPurchaseOrderDO.setMainOrderId(no);
            // 合计价格
            BigDecimal totalPrice = new BigDecimal("0");
            purPurchaseOrderDO.setTotalPrice(totalPrice);
            purPurchaseOrderDO.setOrderTime(LocalDateTime.now());

            // 循环整合单，找到每个供应商商品
            for (DepPurchaseItemDO depPurchaseItem : DepPurchaseItemDOs) {
                if (depPurchaseItemDO.getSupplierDeptId().equals(depPurchaseItem.getSupplierDeptId())) {
                    PurPurchaseOrderItemDO purPurchaseOrderItemDO = new PurPurchaseOrderItemDO();
                    // 汇总总价格
                    totalPrice = totalPrice.add(depPurchaseItem.getProductPrice().multiply(depPurchaseItem.getCountActual()));
                    // 采购单
                    purPurchaseOrderItemDO.setPurchaseOrderId(id);
                    // 设置采购订单项的商品ID
                    purPurchaseOrderItemDO.setProductId(depPurchaseItem.getProductId());
                    // 设置采购订单项的数量
                    purPurchaseOrderItemDO.setCount(depPurchaseItem.getCountActual());
                    // 设置采购订单项的商品单价
                    purPurchaseOrderItemDO.setProductPrice(depPurchaseItem.getProductPrice());
                    // 设置采购订单项的采购价格
                    // 设置采购订单项的商品单位ID
                    purPurchaseOrderItemDO.setProductUnitId(depPurchaseItem.getProductUnitId());
                    // 设置采购订单项的商品单位名称
                    purPurchaseOrderItemDO.setProductUnitName(depPurchaseItem.getProductUnitName());
                    // 设置采购订单项的商品分类ID
                    purPurchaseOrderItemDO.setProductCategoryId(depPurchaseItem.getProductCategoryId());
                    // 设置采购订单项的商品分类名称
                    purPurchaseOrderItemDO.setProductCategoryName(depPurchaseItem.getProductCategoryName());
                    // 设置采购订单项的商品名称
                    purPurchaseOrderItemDO.setProductName(depPurchaseItem.getProductName());
                    // 设置采购订单项的商品规格
                    purPurchaseOrderItemDO.setProductStandards(depPurchaseItem.getProductStandards());
                    // 设置采购订单项的商品分类ID
                    purPurchaseOrderItemDO.setProductCategoryId(depPurchaseItem.getProductCategoryId());
                    // 设置采购订单项的商品分类名称
                    purPurchaseOrderItemDO.setProductCategoryName(depPurchaseItem.getProductCategoryName());
                    // 设置采购订单项的备注
                    purPurchaseOrderItemDO.setRemark(depPurchaseItem.getRemark());
                    // 设置采购订单项的总价
                    purPurchaseOrderItemDO.setTotalPrice(depPurchaseItem.getProductPrice().multiply(depPurchaseItem.getCountActual()));

                    purPurchaseOrderItemDOList.add(purPurchaseOrderItemDO);

                }
            }
            // 总价格
            purPurchaseOrderDO.setTotalPrice(totalPrice);
            purPurchaseOrderDOS.add(purPurchaseOrderDO);
        }
        // 生成采购单
        purPurchaseOrderMapper.insertBatch(purPurchaseOrderDOS);

        // 合并相同 productId 的采购订单项
        Map<Long, PurPurchaseOrderItemDO> mergedItems = new HashMap<>();
        for (PurPurchaseOrderItemDO item : purPurchaseOrderItemDOList) {
            if (mergedItems.containsKey(item.getProductId())) {
                PurPurchaseOrderItemDO existing = mergedItems.get(item.getProductId());
                existing.setCount(existing.getCount().add(item.getCount()));
                existing.setTotalPrice(existing.getTotalPrice().add(item.getTotalPrice()));
            } else {
                mergedItems.put(item.getProductId(), item);
            }
        }
        // 清空原列表，并放入合并后的数据
        purPurchaseOrderItemDOList.clear();
        purPurchaseOrderItemDOList.addAll(mergedItems.values());
        // 生成采购单明细
        purPurchaseOrderItemMapper.insertBatch(purPurchaseOrderItemDOList);
        // 工作流
        BpmTaskApproveReqVO bpmTaskApproveReqVO = new BpmTaskApproveReqVO();
        bpmTaskApproveReqVO.setId(createReqVO.getTaskId());
        bpmTaskApproveReqVO.setReason("通过");
        bpmTasktooService.approveTaskToo(getLoginUserId(), bpmTaskApproveReqVO);

        return null;
    }

    @Override
    public void updatePriWarehouseIntegra(PriWarehouseIntegraSaveReqVO updateReqVO) {
        // 校验存在
        validatePriWarehouseIntegraExists(updateReqVO.getId());
        // 更新
        PriWarehouseIntegraDO updateObj = BeanUtils.toBean(updateReqVO, PriWarehouseIntegraDO.class);
        priWarehouseIntegraMapper.updateById(updateObj);
    }

    @Override
    public void officeAudit(PriWarehouseIntegraSaveReqVO updateReqVO) {
        // 校验存在
        validatePriWarehouseIntegraExists(updateReqVO.getId());
        // 更新
        PriWarehouseIntegraDO updateObj = BeanUtils.toBean(updateReqVO, PriWarehouseIntegraDO.class);
        priWarehouseIntegraMapper.updateById(updateObj);
        // 工作流
        BpmTaskApproveReqVO bpmTaskApproveReqVO = new BpmTaskApproveReqVO();
        bpmTaskApproveReqVO.setId(updateReqVO.getTaskId());
        bpmTaskApproveReqVO.setReason("通过");
        bpmTasktooService.approveTaskToo(getLoginUserId(), bpmTaskApproveReqVO);
    }

    @Override
    public void deletePriWarehouseIntegra(Long id) {
        // 校验存在
        validatePriWarehouseIntegraExists(id);
        // 删除
        priWarehouseIntegraMapper.deleteById(id);
    }

    private void validatePriWarehouseIntegraExists(Long id) {
        if (priWarehouseIntegraMapper.selectById(id) == null) {
            throw exception(PRI_WAREHOUSE_INTEGRA_NOT_EXISTS);
        }
    }

    @Override
    public PriWarehouseIntegraDO getPriWarehouseIntegra(Long id) {
        return priWarehouseIntegraMapper.selectById(id);
    }

    @Override
    public PageResult<PriWarehouseIntegraDO> getPriWarehouseIntegraPage(PriWarehouseIntegraPageReqVO pageReqVO) {
//        Long loginUserId = getLoginUserId();
//        List<Task> taskTodoToo = bpmTasktooService.getTaskTodoToo(loginUserId, taskname1);
        List<Task> taskTodoToo = bpmTasktooService.getTaskTodoTooByTaskName(taskname1);
        List<String> processInstanceIds = taskTodoToo.stream().map(Task::getProcessInstanceId).collect(Collectors.toList());
        if (processInstanceIds.size() == 0) {
            return null;
        }
        pageReqVO.setProcessInstanceIds(processInstanceIds);
        PageResult<PriWarehouseIntegraDO> pageResult = priWarehouseIntegraMapper.selectPage(pageReqVO);
        for (PriWarehouseIntegraDO priWarehouseIntegraDO : pageResult.getList()) {
            for (Task task : taskTodoToo) {
                if (task.getProcessInstanceId().equals(priWarehouseIntegraDO.getProcessInstanceId())) {
                    priWarehouseIntegraDO.setTaskId(task.getId());
                }
            }
        }
        return pageResult;
    }

    @Override
    public PageResult<PriWarehouseIntegraDO> getPriWarehouseIntegraPage2(PriWarehouseIntegraPageReqVO pageReqVO) {
        Long loginUserId = getLoginUserId();
        List<Task> taskTodoToo = bpmTasktooService.getTaskTodoToo(loginUserId, taskname2);
        List<String> processInstanceIds = taskTodoToo.stream().map(Task::getProcessInstanceId).collect(Collectors.toList());
        if (processInstanceIds.size() == 0) {
            return null;
        }
        pageReqVO.setProcessInstanceIds(processInstanceIds);
        PageResult<PriWarehouseIntegraDO> pageResult = priWarehouseIntegraMapper.selectPage(pageReqVO);
        for (PriWarehouseIntegraDO priWarehouseIntegraDO : pageResult.getList()) {
            for (Task task : taskTodoToo) {
                if (task.getProcessInstanceId().equals(priWarehouseIntegraDO.getProcessInstanceId())) {
                    priWarehouseIntegraDO.setTaskId(task.getId());
                }
            }
        }
        return pageResult;
    }

    @Override
    public PageResult<PriWarehouseIntegraDO> getPriWarehouseIntegraPage3(PriWarehouseIntegraPageReqVO pageReqVO) {
        Long loginUserId = getLoginUserId();
        List<Task> taskTodoToo = bpmTasktooService.getTaskTodoToo(loginUserId, taskname3);
        List<String> processInstanceIds = taskTodoToo.stream().map(Task::getProcessInstanceId).collect(Collectors.toList());
        if (processInstanceIds.size() == 0) {
            return null;
        }
        pageReqVO.setProcessInstanceIds(processInstanceIds);
        PageResult<PriWarehouseIntegraDO> pageResult = priWarehouseIntegraMapper.selectPage(pageReqVO);
        for (PriWarehouseIntegraDO priWarehouseIntegraDO : pageResult.getList()) {
            for (Task task : taskTodoToo) {
                if (task.getProcessInstanceId().equals(priWarehouseIntegraDO.getProcessInstanceId())) {
                    priWarehouseIntegraDO.setTaskId(task.getId());
                }
            }
        }
        return pageResult;
    }

    @Override
    public void submitOffice(String taskId) {
        BpmTaskApproveReqVO bpmTaskApproveReqVO = new BpmTaskApproveReqVO();
        bpmTaskApproveReqVO.setId(taskId);
        bpmTaskApproveReqVO.setReason("通过");
        bpmTasktooService.approveTaskToo(getLoginUserId(), bpmTaskApproveReqVO);
    }

}